package com.amos.base.service;

import com.amos.base.base.BaseDTO;
import com.amos.base.base.BaseEntity;
import com.amos.base.base.DefaultDTO;
import com.amos.base.base.Result;
import com.amos.base.entity.CurrentSession;
import com.amos.base.exception.ApplicationException;
import com.amos.base.repository.Repository;
import com.amos.base.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.ParameterizedType;
import java.util.Date;


/**
 * @author Amos
 * @ClassName AbstractService
 * @Description TODO
 * @Date 2018/12/23 11:26
 * @VERSION 1.0
 **/
@Transactional(readOnly = true, rollbackFor = ApplicationException.class)
public abstract class AbstractService<T extends BaseDTO, E extends BaseEntity> implements BaseService<T> {
    public final Logger logger = LoggerFactory.getLogger(this.getClass());
    private Class<T> dtoClass;
    private Class<E> entityClass;

    /**
     * 子类实现repository
     * @return
     */
    protected abstract Repository<E> getRepository();

    /**
     * 子类实现验证方法
     * @param dto
     * @return
     */
    protected abstract Result validate(T dto);

    /**
     * 子类根据需要实现获取登录相关信息
     * @return
     */
    protected abstract CurrentSession getSession();

    /**
     * 子类实现保存属性集相关信息
     * @param dto
     * @param id
     */
    protected abstract void savePropertySet(T dto ,String id);

    /**
     * 子类实现加载属性集相关信息
     * @param dto
     */
    protected abstract void loadPropetySet(T dto);

    public AbstractService() {
//        dtoClass = GenericsUtils.getSuperClassGenricType(AbstractService.class, 0);
//        entityClass = GenericsUtils.getSuperClassGenricType(AbstractService.class, 1);
        dtoClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        logger.info("dtoClass:"+dtoClass.getSimpleName());
        logger.info("entityClass:"+entityClass.getSimpleName());
    }

    /**
     * 查看
     * @param id
     * @return
     */
    @Override
    public T load(String id) {
        if (NullUtils.isEmpty(id)) {
            return null;
        }
        E entity = getRepository().selectByPrimaryKey(id);
        T dto = DataUtils.entity2dto(entity,dtoClass);
        // 子类加载属性集相关信息
        this.loadPropetySet(dto);
        return dto;
    }

    /**
     * 根据Id删除 逻辑删除
     * @param id
     * @return
     */
    @Override
    public int deleteById(String id) {
        return getRepository().deleteByPrimaryKey(id);
    }

    /**
     * 通用保存方法
     * @param dto
     * @return
     */
    @Override
    public Result save(T dto) {
        Result result = this.validate(dto);
        if (!Result.isSuccess(result)) {
            return result;
        }
        try {
            initOperator(dto, dto.isNew());
            String id = UUIDUtil.getUuid();
            if (dto.isNew()) {
                dto.setId(id);
            }
            E entity = DataUtils.dto2Entity(dto, entityClass);
            getRepository().save(entity);
            // 子类实现保存属性集相关配置
            savePropertySet(dto,id);
        }catch (Exception e){
            e.printStackTrace();
            return ResultWapper.ERROR(e.getMessage());
        }
        return ResultWapper.SUCCESS();
    }

    /**
     * 初始化操作相关的信息
     * @param dto
     * @param isNew
     */
    private void initOperator(T dto, boolean isNew){
        if (NullUtils.isNotEmpty(getSession()) && NullUtils.isNotEmpty(getSession().getAccount())) {
            if (isNew) {
                dto.setCreateUser(getSession().getAccount().getId());
            }
            dto.setModifyUser(getSession().getAccount().getIdCard());
        }else {
            if (isNew){
                dto.setCreateTime(new Date());
            }
            dto.setModifyTime(new Date());

        }
    }

}
